Volume 也是 Docker 的元件,它提供 container 保存資料或共享資料的機制。
在開始說明 volume 前,先來看下面這個情境。
昨天學到了如何在背景開啟 HTTP server,指令如下:
$ docker run -d --name web -p 8080:80 httpd
c30dfb2d3261170cd3fc4ed012e8ac441261292b13b95c1f203b8b0b4138d75f
$ curl http://localhost:8080/
<html><body><h1>It works!</h1></body></html>
Server 是開好了,但如果 server 的內容不能依需求修改的話,最終只是拿來玩 Hello world 而已。
因此現在有了新的目標--更新裡面的程式。可以使用 docker exec
加上 shell 進入 container:
# 啟動 Apache
docker run -d --name web -p 8080:80 httpd
# 確認 container 正在執行中
docker ps
# 使用 exec 進入 container
docker exec -it web bash
# 找出 Apache 回 curl 的 HTML
cat htdocs/index.html
docker exec
是在一個運行中的 container 上,再執行一個新的指令。參數為上例的 CONTAINER ID
與啟動 shell 的指令 bash
,執行的結果是進入 Apache container 的世界裡,在裡面可以找得到 curl 取到的 HTML 原始文件。
只要修改這個檔案,即可讓 curl 獲得修改後的檔案。
# 使用 exec 進入 container
docker exec -it web bash
# 使用新的內容取代 index.html 並離開 container
echo Hello volume > htdocs/index.html && exit
# 離開並測試
curl http://localhost:8080/
上面這個範例,我們成功修改了 index.html
的內容。但先別開心,我們把舊的移除,然後用 docker run
跑一個新的 Apache container 看看:
# 確認內容
curl http://localhost:8080/
# 移除 container
docker rm -f web
# 再啟動一次
docker run -d --name web -p 8080:80 httpd
# 確認內容
curl http://localhost:8080/
這個實驗會發現,It works! 又回來了?原因很簡單,在介紹 port forwarding 的時候,有提到隔離特性,也有提到每個 container 都是各自獨立的,這也代表剛剛被砍掉的 container 與現在建立的 container 是不同一個。而使用 docker run
指令產生的 container,每次都會是全新跟重灌好一樣,這就是一次性的特性。
只要開新的 container 就會被砍掉重練,那該如何讓我們寫好的程式出現在 container 裡面呢?方法有很多種,今天說明馬上就能使用的 Bind Mount。
Bind Mount 的概念很簡單,它可以把本機的某個目錄或檔案,綁定在 container 裡的某個目錄或檔案。比方說把目前開發的程式,綁在 container 的 /source
,那 container 就能在它的 /source
裡看到本機的檔案。
綁定使用 -v
選項,下面範例是把目前目錄綁定在 Apache container 的 /usr/local/apache2/htdocs
目錄下:
# 執行 container
docker run -d -it -v `pwd`:/usr/local/apache2/htdocs -p 8080:80 httpd
# 測試對應路徑
curl http://localhost:8080/test.html
這個方法可以簡單解決 docker run
產生新的 container 的情境下保有舊的資料。
docker exec
在一個正在執行的 container 上執行指令,用法如下:
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
docker run
與 docker exec
做的事很相似,決定性差異在於:docker run
會產生新的 container,而 docker exec
需要運行中的 container。
-i|--interactive
和 -t|--tty
參數用法與 docker create
相同。
docker run
-v|--volume
掛載 volume 到這個 container 上,格式為 [/host]:[/container]:[參數]